/*
 * Copyright (c) 2024 iSOFT INFRASTRUCTURE SOFTWARE CO., LTD.
 * easyAda is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */

#ifndef CAPS_CAPABILITY_H
#define CAPS_CAPABILITY_H

#include <stdlib/assert.h>
#include <stdlib/stdint.h>
#include <tools/macros.h>
#include <uapi/caps/capability.h>
#include <uapi/initialcaps.h>

static inline const unsigned int *cap_get_capobj_size(void)
{
    extern const unsigned int capobj_size[];
    return capobj_size;
}

static inline void cap_set_long_info(capability_t *cap, unsigned long info)
{
    cap->w = info;
}

static inline void cap_set_short_info(capability_t *cap, unsigned long info)
{
    assert(info <= lowbitsmask(sizeof(unsigned long) * 8 - CAP_TYPE_BITS));

    cap->ww &= lowbitsmask(CAP_TYPE_BITS);
    cap->ww |= info << CAP_TYPE_BITS;
}

static inline void cap_set_type(capability_t *cap, unsigned long type)
{
    assert(type <= lowbitsmask(CAP_TYPE_BITS));

    cap->ww &= ~lowbitsmask(CAP_TYPE_BITS);
    cap->ww |= type;
}

static inline void cap_basic_init(capability_t *cap, unsigned long type)
{
    cap->parent = cap;
    cap->next   = NULL;
    cap_set_type(cap, type);
}

static inline void cap_copy(capability_t *to, capability_t *from)
{
    assert(to != 0 && from != 0);

    to->next   = from->next;
    to->parent = from->parent;
    if (to->next != NULL) {
        to->next->parent = to;
    }
    from->next = to;

    to->w  = from->w;
    to->ww = from->ww;
}

static inline void cap_make_empty(capability_t *cap)
{
    cap_basic_init(cap, CAP_EMPTY);
}

void cap_dispatcher(unsigned long cptr, unsigned long tag, unsigned long m0, unsigned long m1, unsigned long m2,
                    unsigned long m3, unsigned long m4, unsigned long m5);

typedef void (*cap_dispatcher_t)(capability_t *, unsigned long, unsigned long, unsigned long, unsigned long,
                                 unsigned long, unsigned long, unsigned long);
extern const cap_dispatcher_t       cap_dispatchers[];
extern const unsigned int SHARED_RO capobj_size[];

capability_t *BOOTONLY initial_cspace_init(void *init, void *addrspace, void *faulthandler);

#endif
